package com.distribute.framework.core.lsf;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;

import com.distribute.framework.core.lsf.entity.AppInfo;
import com.distribute.framework.core.lsf.protocol.ILsfChannel;
import com.distribute.framework.core.lsf.protocol.ILsfManager;
import com.distribute.framework.core.web.helper.Utils;
import com.distribute.framework.core.web.helper.SpringBeanHelper;

public class LsfCustomer extends Thread implements InitializingBean,FactoryBean{
	
	private Lsf lsf = null;
	private ILsfManager manager = null;
	static Map<String,Map<String,AppInfo>> mappings = new HashMap();
	
	public LsfCustomer(){}
	public void afterPropertiesSet() throws Exception {
		manager = new LsfRedisManager(lsf);
		synchronized(mappings){
			if(mappings.get(lsf.getFlag())==null){
				mappings.put(lsf.getFlag(),new HashMap());
				this.start();
			}
		}
	}
	public Object getObject() throws Exception {
		return this;
	}
	public Class getObjectType() {
		return LsfCustomer.class;
	}

	public boolean isSingleton() {
		return false;
	}
	
	public void run(){
		while(true){
			try {
				login();
			} catch (Exception e) {
				e.printStackTrace();
				try {
					Thread.sleep(300l);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
			}
			try {
				Thread.sleep(20000l);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 登录到治理中心
	 */
	private void login() {
		Set<AppInfo> servers = manager.login();
		if(servers!=null){
			Map<String,AppInfo> map = new HashMap();
			for(AppInfo appInfo:servers){
				for(String serviceInterface:appInfo.getInterfaces())
					map.put(serviceInterface, appInfo);
			}
			synchronized(mappings){
				mappings.put(lsf.getFlag(), map);
			}
		}
	}

	/**
	 * 根据服务信息获取通道
	 * @param serverInfo
	 * @param serviceInterface 
	 * @return
	 */
	public ILsfChannel getChannel(AppInfo serverInfo, String serviceInterface) {
		String beanName = serverInfo.getVisitKey()+":"+serviceInterface;
		ILsfChannel lsfChannel = Utils.getBean(beanName);
		if(lsfChannel==null){
			BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean.class);
			beanDefinitionBuilder.addPropertyValue("serviceUrl", serverInfo.getUrl());
			beanDefinitionBuilder.addPropertyValue("serviceInterface", ILsfChannel.class.getName());
			beanDefinitionBuilder.setScope("prototype");
			SpringBeanHelper.registerBean(beanName, beanDefinitionBuilder.getBeanDefinition() );
			lsfChannel = Utils.getBean(beanName);
		}
		return lsfChannel;
	}

	public AppInfo getServerInfo(String serviceInterface){
		Map<String, AppInfo> mapping = mappings.get(lsf.getFlag());
		if(mapping==null || mapping.isEmpty())
			return null;
		return mapping.get(serviceInterface);
	}
	
	public Object invoker(String serviceInterface, String methodName, Object... args) throws Exception {
		AppInfo serverInfo = getServerInfo(serviceInterface);
		if(serverInfo==null && !ILsfManager.class.getName().equals(serviceInterface)){
			while((serverInfo = getServerInfo(serviceInterface))==null){
				Thread.sleep(1000l);
				if(Utils.equals(Utils.config("debug"), "true")){
					Utils.trace(Utils.json(mappings));
				}
				Utils.trace("<lsf> - 正在登录注册中心 - "+lsf.getFlag());
			}
		}
		
		ILsfChannel lsfChannel = null;
		try{
			lsfChannel = getChannel(serverInfo,serviceInterface);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new LsfException("<lsf> - 无法连接服务<"+serverInfo.getUrl()+">");
		}
		if(lsfChannel==null)
			throw new LsfException("<lsf> - 找不到服务<"+serverInfo.getUrl()+">的接口<"+serviceInterface+">");
		
		return lsfChannel.invoker(lsf.getFlag(),serverInfo.getVisitKey(), serviceInterface, methodName, args);
	}

	public Lsf getLsf() {
		return lsf;
	}

	public void setLsf(Lsf lsf) {
		this.lsf = lsf;
	}

	
	
	
	
}